home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / System / Felix 1.1 / code128.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-16  |  4.9 KB  |  124 lines  |  [TEXT/KAHL]

  1. /* Felix - June 29th, 1993 */
  2.  
  3. /*
  4.     This is a patch for _FSDispatch. We are interested only in the PBDTGetAPPL routine, which corresponds to selector 0x27.
  5.     We don't do anything unless the Control key is down. If it is, we call StandardGetFile in order to allow the user to choose which
  6.     app he wants to use to open the file.
  7.     
  8.     [1994 note : The details of this patch are very hairy. You should only use the basic techniques: how to check for the selector,
  9.     how to return directly to the caller, how to chain to the original trap.]
  10.  
  11.     Okay, it's not quite that simple... Hairy things happen. If the Finder asks the Disk 1 Desktop Database which app is to be used,
  12.     and if as a result we give an app located on Disk 2, the Finder notices that something's wrong and calls us again with the same
  13.     parameters (only ioIndex is incremented).
  14.     To work around this, we must give an answer to the Finder iff the chosen app is on the same disk as the database we are supposed
  15.     to use. To do that, I use PBDTGetPath with the app's vRefNum, and I compare the resulting ioDTRefNum with the one passed by
  16.     the Finder. If they match, I return the app specification; otherwise, I return afpItemNotFound, and I wait for a call with the right
  17.     ioDTRefNum.
  18.     To do all this, we need globals:
  19.         replyReady        if set, we have already put up a dialog, reply is valid and is waiting to be passed to the Finder.
  20.         reply                contains the file chosen by the user
  21.  
  22. */
  23.  
  24. #include "globals.c"
  25.  
  26. Boolean ControlIsPressed (void);
  27. Boolean GetAPPL (DTPBPtr paramBlock, long *result, GlobalsPtr G);
  28.  
  29. /* Since the Custom Header option is used, main must be the first procedure */
  30.  
  31. void main (void)
  32. {
  33.     long                             selector, result;
  34.     DTPBPtr                    paramBlock;
  35.     GlobalsPtr                    G;
  36.  
  37.     asm {
  38.             movem.l d0-d7/a0-a4, -(SP)                                                                        /* Save registers */
  39.             move.l a0, paramBlock                                                                                    /* Get parameters */
  40.             move.l d0, selector
  41.             move.l @data, G                                                                                            /* Get the globals' address */
  42.     }
  43.     
  44.     if (selector == 0x27) {                                                                                            /* Check for PBDTGetAPPL's selector */
  45.         if (ControlIsPressed() || G->replyReady) {
  46.             if (GetAPPL(paramBlock, &result, G)) {
  47.                 asm {
  48.                     move.l result, (SP)                                                                                /* This will put result into D0 */
  49.                     movem.l (SP)+, d0-d7/a0-a4                                                                /* Restore registers */
  50.                     unlk a6
  51.                     rts                                                                                                        /* Return directly to the caller */
  52.                 }
  53.             }
  54.         }
  55.         else G->replyReady = false;
  56.     }
  57.  
  58.     asm {
  59.             movem.l (SP)+, d0-d7/a0-a4                                                                        /* Restore registers */
  60.             unlk    a6                                                 
  61.             move.l @moof, -(SP)                                                                                        /* And chain to the real _FSDispatch */
  62.             rts
  63.             
  64.     moof:    dc 'Mo', 'of', '!\0'                                                                                         /* Here the loader writes the org trap address */
  65.     data:        dc 'Da', 'ta', '!\0'                                                                                        /* and here a pointer to the globals */
  66.     }
  67. }
  68.  
  69.  
  70. /*     GetAPPL replaces PBDTGetAPPL, and returns a Boolean telling whether the original PBDTGetAPPL should be skipped */
  71.  
  72. #define CurDirStore 0x398                                                                                    /* Contains SFGetFile's current directory */
  73.  
  74. Boolean GetAPPL (DTPBPtr paramBlock, long *result, GlobalsPtr G)
  75. {
  76.     SFTypeList                typeList;
  77.     DTPBRec                    params;
  78.     OSErr                        e;
  79.     
  80.     if (!G->replyReady) {    
  81.         *((long*) CurDirStore) = G->dirID;                                                                /* Set the default directory */
  82.         typeList [0] = 'APPL';                                                                                    /* Show only applications */
  83.         typeList [1] = 'adrp';                                                                                    /* and aliases to applications */
  84.         StandardGetFile (NULL, 2, typeList, &(G->reply));                                        /* Display the dialog */
  85.         if (G->reply.sfGood)                                                                                        
  86.             G->replyReady = true;                                                                                /* Remember we have displayed it */
  87.         else 
  88.             return false;                                                                                                /* The guy cancelled, forget everything */
  89.     }
  90.     
  91.     params.ioNamePtr = nil;                                                                                    /* Make sure that the user chosen app resides */
  92.     params.ioVRefNum = G->reply.sfFile.vRefNum;                                                    /* on the same disk as the desktop database */
  93.     e = PBDTGetPath (¶ms);                                                                            /* which we are supposed to have looked up */
  94.     
  95.     if (e != noErr) {                                                                                                    /* Error: this is probably a disk without a DTDB. */
  96.         G->replyReady = false;                                                                                    /* Let's use the standard routine */
  97.         return false;
  98.     }
  99.     
  100.     if (params.ioDTRefNum != paramBlock->ioDTRefNum) {                                        /* Wrong disk. Let's report we didn't find anything */
  101.         *result = afpItemNotFound;
  102.         return true;
  103.     }
  104.     
  105.     G->replyReady = false;                                                                                        /* Everything's fine, let's return the result */
  106.     *result = noErr;
  107.  
  108.     BlockMove (&(G->reply.sfFile.name), paramBlock->ioNamePtr, 64);                    /* Copy the name */
  109.     paramBlock->ioAPPLParID = G->reply.sfFile.parID;                                            /* and the parent dir ID */
  110.     paramBlock->ioResult = noErr;
  111.     return true;
  112. }
  113.  
  114. /*     ControlIsPressed checks to see whether the Control key is down. This code is taken out of THINK Ref 2.0 */
  115.  
  116. #define ControlScanCode 0x3B
  117.  
  118. Boolean ControlIsPressed (void)
  119. {
  120.     unsigned char km[16];
  121.  
  122.     GetKeys ((long *) km);
  123.     return ((km [ControlScanCode >> 3] >> (ControlScanCode & 7)) & 1);
  124. }